4.7 类型转换
我们已经在之前的章节中学习过了Go
语言的基本数据类型。
在实际的应用场景中,我们很多时候都会需要进行类型转换。
这一节我们将针对类型转换进行详细的介绍。
本节代码存放目录为 lesson12
什么是类型转换?
我们之前学习到了int
、string
、float32
等基本数据类型。
那么如果我需要将int
类型的变量转换为string
类型的值进行输出应该怎么办呢?
这就需要使用到类型转换的功能。
类型转换用于基本数据类型之间的相互转换,唯一有一个特殊的就是interface
。
在上一节我们已经讲解过了interface
可以是任意类型,那么我们在使用的时候就需要进行类型转换以拿到实际的值进行运算等操作。
基本数据类型转换
在Go
语言中提供了strconv
包来进行基本的数据类型转换,下面我们将演示其中比较常用的一些使用方式。
对于相同类型的数据类型转换,比如int
转换为int32
、int32
转换为int64
。我们可以这样做:
var a int = 1
fmt.Println(int32(a))
var b int32 = 2
fmt.Println(int64(b))
在上面的代码中,我们通过int32()
、int64()
就可以直接将其转换为相应的类型。
那么同样的,我们也可以使用int()
、int32()
将int64
位的类型进行转换。
但是需要注意的是:如果int64
类型的数据特别大,已经超出了int32
类型所能表示的数字,那么超过的部分将会被截断。
对于整型转换为string
字符串类型,我们可以这样做:
var c int64 = 3
var d string = strconv.FormatInt(c, 10)
fmt.Println(d)
在上面的代码中,我们使用strconv.FormatInt
将数字转换为了一个字符串。
其中10
代表的是:c
变量为十进制的数字。
在实际的使用中,我们也可以使用下面的方法进行转换:
fmt.Println(fmt.Sprintf("%d", c))
在上面的代码中,我们使用了fmt.Sprintf
进行处理,事实上是利用了fmt.Sprintf
格式化输出的特性,将其转换为了一个字符串。
我们也会经常遇到将string
字符串类型转换为其他类型的场景。如下所示:
e, _ := strconv.Atoi(d)
fmt.Println(e)
f, _ := strconv.ParseInt(d, 10, 64)
fmt.Println(f)
在上面的代码中,我们使用了两种方法。
第一种是strconv.Atoi
,这种方法平常我们会用于将字符串转换为int
类型。
第二种是strconv.ParseInt
,最终转换出的会是一个int64
类型的值,我们可以进步一的通过int32()
、int()
转换为需要的类型。
其中10
表示的是:字符串是一个10
进制的数组,64
表示的是目标类型的位数,可以理解为就是int64
,那么也可以定义为32
,表示需要转换为int32
位数的数字。
除了上述我们讲到的,还有其他基本数据类型的相互转换,可以去看一下Go
语言的strconv
包,里面包含了各种转换方法,同时也包含了很多不错的算法理念。
interface类型转换
在之前我们讲解到了interface
可以表示任意类型,如下定义:
var g interface{}
g = 1;
在上面的代码中,我们将g
变量定义为了interface
类型,同时为g
变量赋值为整数11
那么我们可以像下面这样取出int
型的值:
h, ok := g.(int)
fmt.Println(ok)
fmt.Println(h)
在上面的代码中,我们通过g.(int)
取出了两个值。
一个是实际的int
类型变量h
,一个是表示是否转换成功的ok
布尔值。
我们也可以不接受ok
布尔值,像下面这样直接获取值:
g.(int)
需要注意的是,如果g
存储的值实际不是一个int
型的,那么当程序执行的时候会发生报错。
那么当我们不知道实际的类型是什么时,我们应该怎么去做呢?
这就涉及到了Go
语言里面的一个概念,叫做类型断言。我们可以这样做:
switch g.(type) {
case int:
fmt.Println(g.(int))
case string:
fmt.Println(g.(string))
}
在上面的代码中,我们取出了g
变量的实际类型,之后通过实际类型去取得值。
这样就可以避免在我们不知道实际类型的情况下而出现错误。
结构体与string
在之前我们讲解过了结构体,那么在实际的应用中,我们可能需要将结构体转换为一个string
类型的字符串
比如我们需要将结构体的值存储在数据库中,那么我们一般会选择将结构体转换为一个字符串进行存储。如下代码所示:
type Student struct {
Name string
Sex string
Age int
}
s := Student{
Name: "小明",
Sex: "男",
Age: 11,
}
sStr := string(sByte)
fmt.Println(sStr)
在上面的结构体中,我们定义了一个Student
结构体,初始化声明了变量并且进行了赋值。
之后我们通过json.Marshal(s)
对结构体进行了转换。
转换后得到了变量sByte
,变量的类型是:[]byte
,该变量可以直接通过string()
转换得到实际的字符串。
结果输出如下所示:
{"Name":"小明","Sex":"男","Age":11}
那么我们应该如何将字符串转换为结构体呢?我们可以使用Unmarshal
。如下代码所示:
var sP Student
json.Unmarshal([]byte(sStr), &sP)
fmt.Println(sP)
在上面的代码中,我们声明了一个新的结构体变量sP
,之后使用Unmarshal
进行转换,将字符串转换为了结构体。
在上面的例子中,结构体转换为字符串,我们称之为Json String
,也就是Json
的概念。
在Json
中,我们可以控制转换为字符串以后字段的名称,如下代码所示:
type Student struct {
Name string `json:"name"`
Sex string `json:"sex"`
Age int `json:"age"`
}
在上面的代码中,定义结构体时我们增加了json:"name"
这样的内容,这被称之为tag
新增tag
以后,我们输出如下:
{"name":"小明","sex":"男","age":11}
小结
在本节中,我们讲解了基础数据类型中间的相关转换、interface
的转化以及结构体与字符串Json String
的转换。
关于本节总结如下:
基础数据类型之间可以进行相互转换
当较大数据转换为较小数据类型时,可能被截断
基础数据类型的转换主要使用
strconv
官方标准库实现interface
转换时需要判断原本的数据类型,在Go
语言中称之为断言结构体的转换也可以称之为编码解码,使用
Marshal
及Unmarshal
实现